package com.yuandian.utils.poi;

import com.alibaba.excel.context.AnalysisContext;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 默认的Excel解析监听器，如有定制化的校验规则，请自定义监听器继承AbstractExcelEventListener
 * </p>
 *
 * @author: tangqingchun
 * @date: 2020-09-03
 */
@Slf4j
public class ExcelDefaultSaveListener<T> extends AbstractExcelEventListener<T> {

    /**
     * Excel解析操作service，提供校验与保存接口
     */
    private ExcelService<T> excelService;

    /**
     * 批量保存数量
     */
    private static final int BATCH_COUNT = 3000;

    /**
     * 校验成功结果集
     */
    private final List<T> resultList = new ArrayList<>();

    /**
     * 校验失败结果集
     */
    private final List<T> failList = new ArrayList<>();

    /**
     * 解析时校验成功结果集
     */
    private List<T> tempList = new ArrayList<>();

    public ExcelDefaultSaveListener(ExcelService<T> excelService){
        this.excelService = excelService;
    }

    /**
     * 每条数据解析的时候都会调用此方法
     *
     * @param data
     * @param context
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        // 业务逻辑判断，调用ExcelService子类方法
        if (!excelService.checkExcelData(data)) {
            failList.add(data);
            return;
        }
        tempList.add(data);
        if (tempList.size() >= BATCH_COUNT){
            // 保存之前进行一次批量校验再入库
            checkAndSaveBatchExcelData(tempList);
        }
    }

    /**
     * 校验解析阶段校验成功的数据并保存
     *
     * @param dataList 解析阶段校验成功的数据
     * @return
     */
    private void checkAndSaveBatchExcelData(List<T> dataList) {
        BatchDataResult<T> batchDataResult = excelService.checkBatchExcelData(dataList);
        if (batchDataResult == null) {
            resultList.addAll(tempList);
            excelService.saveBatchExcelData(tempList);
            tempList.clear();
            return;
        }
        if (batchDataResult.getSuccessResult() != null) {
            resultList.addAll(batchDataResult.getSuccessResult());
        }
        if (batchDataResult.getFailResult() != null) {
            failList.addAll(batchDataResult.getFailResult());
        }
        // 入库前批量校验成功才调用保存
        if (batchDataResult.isSuccess()) {
            excelService.saveBatchExcelData(batchDataResult.getSuccessResult());
            tempList.clear();
        }
    }

    /**
     * 所有数据解析完成后执行
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 保存，防止有遗留数据
        if (tempList.size() > 0){
            checkAndSaveBatchExcelData(tempList);
        }
        log.info("导入完成! 成功: {}条, 失败: {}条! ", resultList.size(), failList.size());
    }

    /**
     * 获取Excel解析结果
     *
     * @return
     */
    @Override
    public Map<String, List<T>> getResultMap(){
        Map<String, List<T>> resultMap = new HashMap<>(2);
        resultMap.put("result", resultList);
        resultMap.put("fail", failList);
        return resultMap;
    }

    /**
     * 获取校验成功结果集
     *
     * @return
     */
    @Override
    public List<T> getSuccessResult() {
        return resultList;
    }

    /**
     * 获取校验失败结果集
     *
     * @return
     */
    @Override
    public List<T> getFailResult() {
        return failList;
    }
}
